﻿//  Copyright (c) 2011 Ray Liang (http://www.dotnetage.com)
//  Dual licensed under the MIT and GPL licenses:
//  http://www.opensource.org/licenses/mit-license.php
//  http://www.gnu.org/licenses/gpl.html

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using DNA.IO.Compress;
using DNA.Utility;
using DNA.Mvc.Installation;

namespace DNA.Mvc.Controllers
{
    public class DeployController : Controller
    {
        private readonly string tmpFolder = "~/shared/temp";
        private WebSiteContext _context;

        public DeployController(WebSiteContext context) { _context = context; }

        [SiteControlPanel(ResKey = "RES_DEPLOY", Sequence = 5)]
        [SecurityAction("Management base", "Upload packages", "Allows users can view and upload packages.",
           PermssionSetResName = "SA_Managementbase",
            TitleResName = "SA_UploadPackage",
            DescResName = "SA_UploadPackageDesc"
            )]
        public ActionResult Index()
        {
            var dir = Server.MapPath(tmpFolder);
            if (!System.IO.Directory.Exists(dir))
                System.IO.Directory.CreateDirectory(dir);

            return View(_context.DataContext.Temporary.All());
        }

        [HttpPost]
        public ActionResult Index(FormCollection forms)
        {
            //if ()
            //    return Redirect("Upload");

            if (Request.Files.Count == 0 || Request.Files[0].ContentLength == 0)
            {
                ViewBag.Error = "Incorrect file format.";
                return RedirectToAction("Index");
            }

            var file = Request.Files[0];
            var ext = System.IO.Path.GetExtension(file.FileName);
            var _name = System.IO.Path.GetFileNameWithoutExtension(file.FileName);
            var _folder = Server.MapPath(tmpFolder + "/" + _name + "/");

            if (!System.IO.Directory.Exists(_folder))
                System.IO.Directory.CreateDirectory(_folder);

            if (ext.Equals(".zip", StringComparison.OrdinalIgnoreCase))
            {
                var extract = new ZipExtract(file.InputStream);
                var files = extract.ReadFiles();
                if (!files.Contains("manifest.xml") && (files.Contains("install.xml")))
                    ViewBag.Error = "The manifest.xml file and install.xml file required!Please ensure these are in the root of the package folder.";
                extract.ExtractTo(_folder);
            }
            else
            {
                ViewBag.Error = "Unrecognize file format! Only *.zip format allow.";
            }
            return RedirectToAction("Index");
        }

        [SecurityAction("Management base", "Remove uploaded packages", "Allows users can remove the uploaded packages.",
                       PermssionSetResName = "SA_Managementbase",
            TitleResName = "SA_RemoveUploadPackage",
            DescResName = "SA_RemoveUploadPackageDesc"
            )]
        public ActionResult Remove(string name)
        {
            var pkg = _GetPackage(name);
            _context.DataContext.Temporary.Delete(pkg);
            return RedirectToAction("Index");
        }

        [SecurityAction("Management base", "Deploy packages", "Allows users can deploy the uploaded packages.",
                       PermssionSetResName = "SA_Managementbase",
            TitleResName = "SA_DeployPackage",
            DescResName = "SA_DeployPackageDesc"
            )]
        public ActionResult Verify(string name)
        {
            var pkg = _GetPackage(name);
            var provider = new DNA.Mvc.UI.FileNodeProvider(pkg.ResolvePhysicalPath());

            provider.GetImageUrl = new Func<string, string>(p =>
            {
                if (System.IO.Path.HasExtension(p))
                {
                    var ext = System.IO.Path.GetExtension(p).Replace(".", "");
                    var fileName = Url.Content("~/content/images/mime/" + ext + ".gif");
                    if (System.IO.File.Exists(Server.MapPath(fileName)))
                        return fileName;
                    return Url.Content("~/content/images/mime/unknow.gif");
                }
                else
                {
                    return Url.Content("~/content/images/folder.gif");
                }

            });
            ViewBag.FileProvider = provider as HierarchicalNodeProviderBase;
            return View(pkg);
        }

        private Package _GetPackage(string name)
        {
            if (string.IsNullOrEmpty(name))
                throw new ArgumentNullException("name");

            var pkg = _context.DataContext.Temporary.Find(p => p.Name.Equals(name, StringComparison.OrdinalIgnoreCase));
            if (pkg == null)
                throw new Exception("Package not found.");

            return pkg;
        }

        [Authorize]
        public ActionResult Exec(string name)
        {
            var logData = new List<TraceData>();

            try
            {
                var pkg = _GetPackage(name);

                var service = new InstallationService();
                var filename = pkg.ResolvePhysicalPath("install.xml");

                var settings = new Dictionary<string, object>();
                var web = _context.Web;
                var _vals = ObjectHelper.ConvertObjectToDictionary(web);

                foreach (var key in _vals.Keys)
                    settings.Add("Web." + key, _vals[key]);
                settings.Add("AppPath", Server.MapPath("~/"));
                service.Install(filename, HttpContext, settings);

                _context.DataContext.Temporary.Delete(pkg);
                var data = service.GetTraceResult();

                logData.AddRange(data);
            }
            catch (Exception e)
            {
                logData.Add(new TraceData("Installation fail! " + e.Message) { ErrorInfo = e, Category = "Error", IsWarn = true });
                return View("Log", logData);
            }

            if (logData.FirstOrDefault(t => t.IsError) != null)
                logData.Add(new TraceData("Installation fail some error occurs!") { Category = "Error", IsWarn = true });
            else
                logData.Add(new TraceData("Install successful!"));

            return View("Log", logData);
        }


    }
}